/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.chl.angholt.bookproject;

import edu.chl.angholt.bookproject.db.AuthorJpaCtrl;
import edu.chl.angholt.bookproject.db.BookJpaCtrl;
import edu.chl.angholt.bookproject.db.Database;
import edu.chl.angholt.bookproject.db.EntityJpaCtrl;
import edu.chl.angholt.bookproject.db.UserJpaCtrl;
import edu.chl.angholt.bookproject.db.entity.Author;
import edu.chl.angholt.bookproject.db.entity.Book;
import edu.chl.angholt.bookproject.db.entity.User;
import edu.chl.angholt.bookproject.db.exception.NonexistentEntityException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author Maria
 * Servlet to handle requests that involve the 
 */
@WebServlet(name = "DBServlet", urlPatterns = {"/DBServlet"})
public class DBServlet extends HttpServlet {

    @XmlRootElement
    static class BookList {

        @XmlElement
        private List<Book> books; // name shows up in XML

        public BookList() {
        }

        public BookList(List<Book> books) {
            this.books = books;
        }
    }

    @XmlRootElement
    static class aBook {

        @XmlElement
        private Book book; // name shows up in XML

        public aBook() {
        }

        public aBook(Book book) {
            this.book = book;
        }
    }

    @XmlRootElement
    static class AuthorList {

        @XmlElement
        private List<Author> authors; // name shows up in XML

        public AuthorList() {
        }

        public AuthorList(List<Author> authors) {
            this.authors = authors;
        }
    }

    @XmlRootElement
    static class aAuthor {

        @XmlElement
        private Author author; // name shows up in XML

        public aAuthor() {
        }

        public aAuthor(Author author) {
            this.author = author;
        }
    }

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {

            AuthorJpaCtrl authorCtrl = Database.getAuthorController();
            BookJpaCtrl bookCtrl = Database.getBookController();
            UserJpaCtrl userCtrl = Database.getUserController();

            String action = request.getParameter("action");

            if (action != null) {                    //Check of action null
                if (action.equals("findAuthor")) {   //Check if author exists
                    String value = request.getParameter("what");
                    response.setContentType("text/plain;charset=UTF-8");
                    if (authorCtrl.findAuthor(value) == null) {  // was not found
                        out.print("false");
                    } else {                                     //was found
                        out.print("true");
                    }
                } else if (action.equals("addAuthor")) {    //Add an author to the database
                    authorCtrl.create(new Author(request.getParameter("name"),
                            request.getParameter("country"),
                            request.getParameter("biography"),
                            request.getParameter("webSite")));

                    User user = (User) request.getSession().getAttribute("user");
                    if (user.getName().equals("admin")) {
                        request.getRequestDispatcher("WEB-INF/jsp/adminpage.jspx").forward(request, response);
                    } else {
                        request.getRequestDispatcher("WEB-INF/jsp/mypage.jspx").forward(request, response);
                    }
                } else if (action.equals("findBook")) {     //Check is a book exists
                    String value = request.getParameter("what");
                    response.setContentType("text/plain;charset=UTF-8");
                    if (bookCtrl.findBook(value) == null) {
                        out.print("false");
                    } else {
                        out.print("true");
                    }
                } else if (action.equals("addBook")) {      //Add a book to the database
                    Calendar cal = Calendar.getInstance();
                    cal.set(new Integer(request.getParameter("year")), Calendar.JANUARY, 1);
                    Author a = authorCtrl.findAuthor(request.getParameter("author"));
                    Book b = new Book(cal,
                            request.getParameter("synopsis"),
                            request.getParameter("title"),
                            request.getParameter("language"),
                            request.getParameter("publicher"),
                            a);

                    try {
                        bookCtrl.create(b);   // comiting it
                    } catch (Exception e) {
                        System.out.println(e.fillInStackTrace());
                    } finally {
                        User user = (User) request.getSession().getAttribute("user");
                    if (user.getName().equals("admin")){
                        request.getRequestDispatcher("WEB-INF/jsp/adminpage.jspx").forward(request, response);
                    } else {
                        request.getRequestDispatcher("WEB-INF/jsp/mypage.jspx").forward(request, response);
                    }

                    }
                } else if (action.equals("findReadBooks")) {    //Get a list of all the books a user has read
                    User user = (User) request.getSession().getAttribute("user");
                    List<Book> books = userCtrl.getReadBooks(user);
                    BookList wrapper = new BookList(books);
                    JAXBContext jc;
                    try {
                        jc = JAXBContext.newInstance(BookList.class);
                        Marshaller m = jc.createMarshaller();
                        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                                Boolean.TRUE);
                        // Dump XML data
                        m.marshal(wrapper, out);
                    } catch (JAXBException ex) {
                        Logger.getLogger(DBServlet.class.getName()).log(Level.SEVERE, null, ex);
                    } finally {
                        out.close();
                    }

                } else if (action.equals("addReadBook")) {      //Add a book to a users list of read books
                    boolean result = false;
                    try {
                        String bookId = (String) request.getParameter("book");
                        User user = (User) request.getSession().getAttribute("user");
                        if (bookId != null && bookId.length() > 0 && user != null) {    //Check that the parameters are correct
                            Book book = bookCtrl.findEntity(Long.parseLong(bookId));
                            if (!userCtrl.haveRead(user, book)) {
                                userCtrl.addReadBook(user, book);
                                result = true;
                            }
                        }
                    } catch (Exception e) {
                    } finally {
                        out.print(result);
                        out.close();
                    }
                } else if (action.equals("removeReadBook")) {       //Remove a book from a users list of read books
                    boolean result = false;
                    try {
                        String bookId = (String) request.getParameter("book");
                        User user = (User) request.getSession().getAttribute("user");
                        if (bookId != null && bookId.length() > 0 && user != null) {    //Check that the parameters are correct
                            Book book = bookCtrl.findEntity(Long.parseLong(bookId));
                            userCtrl.removeReadBook(user, book);
                            result = true;
                        }
                    } catch (Exception e) {
                    } finally {
                        out.print(result);
                        out.close();
                    }
                } else if (action.equals("findBookLike")) {
                    List<Book> books = bookCtrl.findBookLike(request.getParameter("what"));
                    BookList wrapper = new BookList(books);
                    JAXBContext jc;
                    try {
                        jc = JAXBContext.newInstance(BookList.class);
                        Marshaller m = jc.createMarshaller();
                        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                                Boolean.TRUE);
                        // Dump XML data
                        m.marshal(wrapper, out);
                    } catch (JAXBException ex) {
                        Logger.getLogger(DBServlet.class.getName()).log(Level.SEVERE, null, ex);
                    } finally {
                        out.close();
                    }
                } else if (action.equals("getBook")) {
                    String bookId = request.getParameter("what");
                    Book book = bookCtrl.findEntity(Long.parseLong(bookId));
                    System.out.println("DBServlet.java" + book.toString());
                    aBook wrapper = new aBook(book);
                    JAXBContext jc;
                    try {
                        jc = JAXBContext.newInstance(aBook.class);
                        Marshaller m = jc.createMarshaller();
                        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                                Boolean.TRUE);
                        // Dump XML data
                        m.marshal(wrapper, out);
                    } catch (JAXBException ex) {
                        Logger.getLogger(DBServlet.class.getName()).log(Level.SEVERE, null, ex);
                    } finally {
                        out.close();
                    }
                } else if (action.equals("removeBook")) {
                    String bookId = request.getParameter("what");
                    try {
                        bookCtrl.destroy(Long.parseLong(bookId));
                        out.print("true");
                    } catch (NonexistentEntityException ex) {
                        Logger.getLogger(DBServlet.class.getName()).log(Level.SEVERE, null, ex);
                        out.print("false");
                    }
                } else if (action.equals("findAuthorLike")) {
                    List<Author> authors = authorCtrl.findAuthorLike(request.getParameter("what"));
                    AuthorList wrapper = new AuthorList(authors);
                    JAXBContext jc;
                    try {
                        jc = JAXBContext.newInstance(AuthorList.class);
                        Marshaller m = jc.createMarshaller();
                        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                                Boolean.TRUE);
                        // Dump XML data
                        m.marshal(wrapper, out);
                    } catch (JAXBException ex) {
                        Logger.getLogger(DBServlet.class.getName()).log(Level.SEVERE, null, ex);
                    } finally {
                        out.close();
                    }
                } else if (action.equals("getAuthor")) {
                    String authorId = request.getParameter("what");
                    Author author = authorCtrl.findEntity(Long.parseLong(authorId));
                    System.out.println("DBServlet.java" + author.toString());
                    aAuthor wrapper = new aAuthor(author);
                    JAXBContext jc;
                    try {
                        jc = JAXBContext.newInstance(aAuthor.class);
                        Marshaller m = jc.createMarshaller();
                        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                                Boolean.TRUE);
                        // Dump XML data
                        m.marshal(wrapper, out);
                    } catch (JAXBException ex) {
                        Logger.getLogger(DBServlet.class.getName()).log(Level.SEVERE, null, ex);
                    } finally {
                        out.close();
                    }
                } else if (action.equals("removeAuthor")) {
                    String authorId = request.getParameter("what");
                    try {
                        authorCtrl.destroy(Long.parseLong(authorId));
                        out.print("true");
                    } catch (NonexistentEntityException ex) {
                        Logger.getLogger(DBServlet.class.getName()).log(Level.SEVERE, null, ex);
                        out.print("false");
                    }
                } else if (action.equals("alterBook")) {
                    Long bookId = Long.parseLong(request.getParameter("bookid"));
                    String title = request.getParameter("title");
                    Author author = authorCtrl.findAuthor(request.getParameter("author"));
                    System.out.println("author " + author);
                    String synopsis = request.getParameter("synopsis");
                    String orginalLanguage = request.getParameter("language");
                    String yearOfRelease = request.getParameter("year");
                    String publicher = request.getParameter("publicher");
                    Calendar cal = Calendar.getInstance();
                    cal.set(new Integer(2000), Calendar.JANUARY, 1);

                    Book book = new Book();
                    book.setBookId(bookId);
                    book.setTitle(title);
                    book.setAuthor(author);
                    book.setSynopsis(synopsis);
                    book.setOriginalLanguage(orginalLanguage);
                    book.setFirstRelease(cal);
                    book.setPublisher(publicher);
                    try {
                        bookCtrl.updateBook(book);
                    } catch (NonexistentEntityException ex) {
                        Logger.getLogger(DBServlet.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    request.getRequestDispatcher("WEB-INF/jsp/adminpage.jspx").forward(request, response);
                } else if (action.equals("alterAuthor")) {
                    Long authorId = Long.parseLong(request.getParameter("authorid"));
                    String name = request.getParameter("name");
                    String country = request.getParameter("country");
                    String biography = request.getParameter("biography");
                    String webSite = request.getParameter("webSite");

                    Author author = new Author();
                    author.setAuthorId(authorId);
                    author.setName(name);
                    author.setCountry(country);
                    author.setBiography(biography);
                    author.setWebSite(webSite);

                    try {
                        authorCtrl.updateBook(author);
                    } catch (NonexistentEntityException ex) {
                        Logger.getLogger(DBServlet.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    request.getRequestDispatcher("WEB-INF/jsp/adminpage.jspx").forward(request, response);
                }
            }
        } finally {
            out.close();
        }
    }
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">

    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
